/**
 *  校验工具
 *  @author MiiKio
 *  @createtime 2022.7.4
 */

const { hasOwnProperty } = Object.prototype

/** 正则校验 */
export const Reg = {
  /** 正整数 */
  integer: /^\d+$/,
  /** 大于0的整数 */
  integerGt0: /^[1-9]\d*$/,
  /** 浮点数 */
  float: /^\d*\.\d+$/,
  /** 大于0的浮点数 */
  floatGt0: /^([1-9]\d*\.\d+|\d*\.(0*[1-9]+0*)+)$/,
  /** 双精度浮点数 (大于等于0的整数或最多两位小数的浮点数) */
  double: /^(0|[1-9]\d*)(\.\d{1,2})?$/,
  /** 任意数字 (支持2-10进制、正负数、浮点数、非科学计数法) */
  number: /^-?(\d+|\d+\.\d*|\d*\.\d+)$/,
  /** 手机号码 */
  mobilePhone: /^1[3-9]\d{9}$/,
  /** 固定电话号码 */
  telephone: /^(\d{3,4}-)?\d{7,8}$/,
  /** 手机/固定电话号码 */
  phone: /^(1[3-9]\d{9}|(\d{3,4}-)?\d{7,8})$/,
  /** 邮箱地址 */
  email: /^[0-9A-Za-z]+[0-9A-Za-z._-]*@[0-9A-Za-z_-]+(\.[0-9A-Za-z_-]+)+$/,
  /** 身份证号码 */
  idCard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
  /** 中文字符 */
  chinese: /^[\u4e00-\u9fa5]+$/,
  /** 英文字符 */
  english: /^[A-Za-z]+$/,
  /** 大写英文字符 */
  englishUpper: /^[A-Z]+$/,
  /** 小写英文字符 */
  englishLower: /^[a-z]+$/,
  /** 标准链接 */
  url: /^(https?|ftps?):\/\/.+/,
  /** 图片链接 */
  imageUrl: /^(https?:\/\/|data:image\/.+?;base64,).+/,
  /** base64数据 */
  base64: /^data:.+?;base64,.+/,
  /** 以空白符开头或结尾 */
  spaceBothside: /^(\s+.*|.*\s+)$/
}

/** 校验对象是否存在属性 */
export function hasProp(val, prop, deep) {
  return val != null && (deep ? prop in val : hasOwnProperty.call(val, prop))
}

/** 校验是否为对象 */
export function isObject(val, like) {
  return val != null && (typeof val == 'object' || (like && typeof val == 'function'))
}

/** 校验是否为数组 */
export function isArray(val, like) {
  return like ? val != null && isValidLength(val.length) && typeof val != 'function' : Array.isArray(val)
}

/** 校验是否为函数 */
export function isFunction(val) {
  return typeof val == 'function'
}

/** 校验是否为Promise */
export function isPromise(val, like) {
  return val != null && (like ? typeof val == 'object' && typeof val.then == 'function' : val instanceof Promise)
}

/** 校验是否为数字或非空文本 */
export function isValidText(val) {
  return (typeof val == 'string' && val !== '') || (typeof val == 'number' && isFinite(val))
}

/** 校验是否为有效长度 */
export function isValidLength(val) {
  return typeof val == 'number' && val > -1 && val % 1 == 0 && val <= 9007199254740991
}

/** 校验是否为有效数字 */
export function isValidNumber(val) {
  return (typeof val == 'number' || (typeof val == 'string' && val !== '')) && isFinite(val)
}

/** 校验是否为数字 (支持2-10进制、正负数、浮点数、非科学计数法) */
export function isNumber(val) {
  return Reg.number.test(val)
}

/** 校验是否为手机号码或电话号码 */
export function isPhone(val, type) {
  return type == 'mobilePhone' || type == 1 ? Reg.mobilePhone.test(val)
    : type == 'telephone' || type == 2 ? Reg.telephone.test(val)
    : Reg.phone.test(val)
}

/** 校验是否为邮箱 */
export function isEmail(val) {
  return Reg.email.test(val)
}

/** 校验是否为身份证号码 */
export function isIdCard(val) {
  return Reg.idCard.test(val)
}

/* 校验是否为中文字符*/
export function isChinese(val) {
  return Reg.chinese.test(val)
}

/* 校验是否为大写或小写英文字符*/
export function isEnglish(val, type) {
  return type == 'upper' || type == 1 ? Reg.englishUpper.test(val)
    : type == 'lower' || type == 2 ? Reg.englishLower.test(val)
    : Reg.english.test(val)
}

/** 校验是否为URL地址 */
export function isURL(val) {
  return Reg.url.test(val)
}

/** 校验是否为图片链接 */
export function isImageLink(val) {
  return Reg.imageUrl.test(val)
}

/** 校验是否为Base64数据 */
export function isBase64(val, contentType) {
  return RegExp(`^data:${require('./utils').toRegSource(contentType) || '.+?'};base64,.+`).test(val)
}

/** 校验是否为Vue的VNode节点 */
export function isVNode(val, componentName) {
  return val != null && typeof val == 'object' && !!(componentName
    ? val.tag && val.componentOptions && val.componentOptions.Ctor.options.name === componentName
    : hasOwnProperty(val, 'componentOptions'))
}
